package com.express.boot.config.security;

/**
 * @author 张成
 * @version 1.0
 * @date 2022/2/20 19:03
 */


import com.express.boot.domain.User;
import com.express.boot.service.UserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.Set;

public class CustomRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    public void setName(String name){
        super.setName("CustomRealm");
    }

    /**
     * 授权
     *      操作的时候用户是否具有相应的权限
     *          先认证 -- 安全数据
     *          再授权 -- 根据安全数据获取用户具有的所有操作权限
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //1. 获取已认证的用户数据
        User user = (User) principals.getPrimaryPrincipal(); //得到唯一的安全数据
        //2. 根据用户数据获取用户的权限信息（所有角色，所有权限）
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> roles = new HashSet<>();
        Set<String> perms = new HashSet<>();
//        for (Role role : user.getRoles()){
//            roles.add(role.getName());
////            for (Permission perm : role.getPermissions()){
////                perms.add(perm.getCode());
////            }
//        }
//        roles.add();
        info.setStringPermissions(perms);
        info.addRole("ccc");
        return info;
    }

    /**
     * 认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//        //1. 登录的用户名密码
//        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
//        String username = upToken.getUsername();
//        String password = new Md5Hash(upToken.getPassword(),username, 3).toString();
//        //2. 根据用户名查询数据库
////        User user = userService.loadUserByUsername(username);
//        //3. 判断用户是否存在或密码是否一致
//        if(user != null && user.getPassword().equals(password)){
//            //4. 如果一致返回安全数据
//            //构造方法：安全数据（自己构造的对象），密码，realm域名称
//            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
//            return info;
//        }
        //5. 不一致，返回null（抛出异常）
        //获取用户的输入的账号.
        String username = (String) token.getPrincipal();
        //通过username从数据库中查找 User对象，如果找到进行验证
        //实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
        User user = userService.loadUserByUsername(username);
        //判断账号是否存在
        if (user == null) {
            throw new AuthenticationException();
        }
//        //判断账号是否被冻结
//        if (user.getState()==null||user.getState().equals("PROHIBIT")){
//            throw new LockedAccountException();
//        }
        //进行验证
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user,                                  //用户名
                user.getPassword(),                    //密码
                ByteSource.Util.bytes("RvP3UID2n30Q2sycZYvH"), //设置盐值
                getName()
        );

        //验证成功开始踢人(清除缓存和Session)
//        ShiroUtils.deleteCache(username,true);
        return authenticationInfo;
    }
}
